package cn.xm.basic.service.impl;

import cn.xm.basic.config.BussinessException;
import cn.xm.basic.constant.BaseConstant;
import cn.xm.basic.dto.PhoneSmsDto;
import cn.xm.basic.service.VerifyCodeService;
import cn.xm.basic.util.SendSmsUtil;
import cn.xm.basic.util.StrUtils;
import cn.xm.basic.util.VerifyCodeUtils;
import cn.xm.user.domain.Logininfo;
import cn.xm.user.domain.User;
import cn.xm.user.mapper.LogininfoMapper;
import cn.xm.user.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class VerifyCodeServiceImpl implements VerifyCodeService {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private LogininfoMapper logininfoMapper;
    @Override
    public String getImageCode(String key) {
        // 生成随机数
        String randomCode = StrUtils.getRandomString(4);
        // 保存到redis
        redisTemplate.opsForValue().set(key,randomCode);
        // 返回图片给前端
        return VerifyCodeUtils.VerifyCode(100,35,randomCode);
    }

    /**
     * 发送短信
     * @param dto
     */
    @Override
    public void sendSmsCode(PhoneSmsDto dto) {
        if ("register".equals(dto.getType())) {
            // 注册
            // 验证图片验证码
            verifyImageCode(dto);
            // 发送验证码
            smsCodeSend(String.format(BaseConstant.verifyCodeCons.REGISTER_SMSCODE_PHOEN, dto.getPhone()));
        } else if ("binder".equals(dto.getType())) {
            // 绑定
            // 没有图片验证码，直接发送验证码
            smsCodeSend(String.format(BaseConstant.verifyCodeCons.BINDER_SMSCODE_PHOEN, dto.getPhone()));
        }

    }

    private void smsCodeSend(String redisKey) {
        // 发送间隔是否小于60s
        // 先取出redis中的短信验证码，有则需要判断时间，没有则是第一次或验证码过期，就直接发短信
        String redisSmsCode = (String)redisTemplate.opsForValue().get(redisKey); // key: register:smscode:phone
        if (redisSmsCode != null) {
            Long expire = redisTemplate.getExpire(redisKey, TimeUnit.MINUTES);
            if (expire >= 4) {
                throw new BussinessException("发送短信过于频繁，稍后再试");
            }
        }
        // 生成验证码
        String smsCode = StrUtils.getRandomString(4);
        log.info("验证码为：{}",smsCode);
        // 存入到redis，生命为5分钟
        redisTemplate.opsForValue().set(redisKey,smsCode,5,TimeUnit.MINUTES);
        // 发送短信
//        SendSmsUtil.sendSms(dto.getPhone(),"你好，验证码为:" + smsCode + ",五分钟内有效");
    }

    private void verifyImageCode(PhoneSmsDto dto) {
        // 验证手机号，验证码的值,uuid是否为空
        if (StringUtils.isBlank(dto.getImageCodeValue())) {
            throw new BussinessException("验证码的值不能为空");
        }
        if (StringUtils.isBlank(dto.getImageCodeValue())) {
            throw new BussinessException("UUID不能为空");
        }
        /*
         * 图片验证码的值是否正确
         * 先取出存放在redis(uuid-验证码的值)中的值,
         */
        String redisValue = (String) redisTemplate.opsForValue().get(dto.getImageCodeKey());
        if (StringUtils.isBlank(redisValue) || !redisValue.equalsIgnoreCase(dto.getImageCodeValue())) {
            throw new BussinessException("图片验证码错误");
        }
        // 手机号是否已注册
        User user = userMapper.findByPhone(dto.getPhone());
        if (user != null) {
            throw new BussinessException("该手机号已注册");
        }
    }
}
